/**
 * Copyright 2010  Pavel Nemec <nemecp4@gmail.com> <br>
 * <br>
 * License - GPLv3<br>
 *<br>
 * This program is free software; you can redistribute it and/or modify<br>
 * it under the terms of the GNU General Public License as published by<br>
 * the Free Software Foundation; either version 3 of the License, or<br>
 * (at your option) any later version.<br>
 *<br>
 * This program is distributed in the hope that it will be useful,<br>
 * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
 * GNU General Public License for more details.<br>
 *<br>
 * You should have received a copy of the GNU General Public License<br>
 * along with this program. If not, see <http://www.gnu.org/licenses/>.<br>
 *<br>
 */
package eu.whowie.jast.client.nat;

/**
 * Copyright 2010  Pavel Nemec <nemecp4@gmail.com> <br>
 * <br>
 * License - GPLv3<br>
 *<br>
 * This program is free software; you can redistribute it and/or modify<br>
 * it under the terms of the GNU General Public License as published by<br>
 * the Free Software Foundation; either version 3 of the License, or<br>
 * (at your option) any later version.<br>
 *<br>
 * This program is distributed in the hope that it will be useful,<br>
 * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
 * GNU General Public License for more details.<br>
 *<br>
 * You should have received a copy of the GNU General Public License<br>
 * along with this program. If not, see <http://www.gnu.org/licenses/>.<br>
 *<br>
 */
import java.util.logging.Logger;

import com.sun.jna.Native;

import eu.whowie.jast.remote.JApplicationInterface;
import eu.whowie.jast.remote.JDialogInterface;
import eu.whowie.jast.remote.JOptionalWidgetFactoryIntervace;
import eu.whowie.jast.remote.JWidgetFactoryInterface;
import eu.whowie.jast.remote.JuiInterface;
import eu.whowie.jast.remote.NewUIInterface;
import eu.whowie.jast.remote.YJLabelInterface;

/**
 * @author Pavel Nemec
 * 
 */
public class JastBinder {
	private Logger logger = Logger.getLogger("JAST_BINDER");
	private BinderInterface binder;

	private final NewUIInterface serverInterface;
	private ObjectMapper<JWidgetFactoryInterface> jWidgetFactoryMapper = new ObjectMapper<JWidgetFactoryInterface>();
	private ObjectMapper<JApplicationInterface> jApplicationMapper = new ObjectMapper<JApplicationInterface>();
	private ObjectMapper<JuiInterface> juiMapper = new ObjectMapper<JuiInterface>();
	private ObjectMapper<JOptionalWidgetFactoryIntervace> jOptionalWidgetFactoryMapper = new ObjectMapper<JOptionalWidgetFactoryIntervace>();
	private ObjectMapper<JDialogInterface> jDialogMapper = new ObjectMapper<JDialogInterface>();
	private ObjectMapper<YJLabelInterface> jLabelMapper = new ObjectMapper<YJLabelInterface>();

	public JastBinder(NewUIInterface serverInterface) {
		this.serverInterface = serverInterface;
		binder = (BinderInterface) Native
				.synchronizedLibrary((BinderInterface) Native.loadLibrary(
						"libjast.so", BinderInterface.class));

	}

	/**
	 * bind c call back for c++ classes to java wrapper
	 */
	public void bind() {

		/***
		 * JUI.h
		 **/
		binder.create_jui(new TopNewCallback() {

			@Override
			public int invoke() {
				return createJui();
			}
		});
		binder.create_application(new NewCallback() {
			@Override
			public int invoke(int parrent) {
				return createApplication(parrent);
			}
		});
		binder.create_widget_factory(new NewCallback() {

			@Override
			public int invoke(int parrent) {
				return createWidgetFactory(parrent);
			}
		});
		binder.create_optional_widget_factory(new NewCallback() {
			@Override
			public int invoke(int parrent) {
				return createOptionalWidgetFactory(parrent);
			}
		});

		binder.dialog_constructor(new ConstructorCallback() {

			@Override
			public int invoke(int parrentId, int dialogType, int colorMode) {
				return createDialog(parrentId, dialogType, colorMode);
			}

		});

		binder.dialog_activate(new SimpleCallback() {
			@Override
			public void invoke(int classId) {
				jDialogMapper.get(classId).activate();
			}
		});

		binder.open_internal(new SimpleCallback() {
			@Override
			public void invoke(int classId) {
				jDialogMapper.get(classId).openInternal();
			}
		});

		binder.label_constructor(new LabelConstructorCallback() {

			@Override
			public int invoke(int parrentId, String text, boolean isHeading,
					boolean isOutput) {
				return createLabel(parrentId, text, isHeading, isOutput);
			}
		});

		binder.label_preffered_height(new SimpleCallbackIntReturn() {
			@Override
			public int invoke(int classId) {
				return jLabelMapper.get(classId).getPrefferedHeight();
			}
		});

		binder.label_preffered_width(new SimpleCallbackIntReturn() {
			@Override
			public int invoke(int classId) {
				return jLabelMapper.get(classId).getPrefferedWidth();
			}
		});

		binder.label_set_size(new YJLabelSetSizeCallback() {

			@Override
			public void invoke(int classId, int w, int h) {
				jLabelMapper.get(classId).setSize(w, h);

			}

		});
	}

	/**
	 * test bounded connection
	 */
	private void test() {
		int i = binder.test_c_java_bindings();
		if (i != 0) {
			logger.warning("tesfinestts failed: " + i);
		} else {
			logger.info("test passed");
		}

	}

	private int createJui() {
		JuiInterface jui = serverInterface.createNewUI();
		int id = juiMapper.storeObject(jui);
		logger.info("j: creating JUI with id: " + id);
		return id;

	}

	public int createWidgetFactory(int parrentId) {
		JuiInterface jui = juiMapper.get(parrentId);
		JWidgetFactoryInterface factory = jui.createWidgetFactory();
		int id = jWidgetFactoryMapper.storeObject(factory);
		return id;
	}

	public int createOptionalWidgetFactory(int parrentId) {
		JuiInterface jui = juiMapper.get(parrentId);
		JOptionalWidgetFactoryIntervace factory = jui
				.createOptionalWidgetFactory();
		int id = jOptionalWidgetFactoryMapper.storeObject(factory);
		return id;
	}

	public int createApplication(int parrentId) {
		JuiInterface jui = juiMapper.get(parrentId);
		JApplicationInterface factory = jui.createApplication();
		int id = jApplicationMapper.storeObject(factory);
		return id;
	}

	private int createDialog(int factoryId, int dialogType, int colorMode) {
		JWidgetFactoryInterface factory = jWidgetFactoryMapper.get(factoryId);
		JDialogInterface dialog = factory.createDialog(dialogType, colorMode);
		return jDialogMapper.storeObject(dialog);
	}

	private int createLabel(int parrentId, String text, boolean isHeading,
			boolean isOutput) {

		JWidgetFactoryInterface factory = jWidgetFactoryMapper.get(parrentId);
		YJLabelInterface label = factory.createLabel(text, isHeading, isOutput);
		return jLabelMapper.storeObject(label);
	}

	public static void main(String argc[]) {
		JastBinder j = new JastBinder(new MockupNewUI());
		j.bind();
		j.test();
	}

}
